package com.dgut.courses_selecting_sys.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dgut.courses_selecting_sys.constants.ActivityStatus;
import com.dgut.courses_selecting_sys.constants.RabbitMqKey;
import com.dgut.courses_selecting_sys.constants.RedisKey;
import com.dgut.courses_selecting_sys.dto.ActivitiesDto;
import com.dgut.courses_selecting_sys.entity.*;
import com.dgut.courses_selecting_sys.mapper.ActivitiesMapper;
import com.dgut.courses_selecting_sys.mapper.UserActivitiesMapper;
import com.dgut.courses_selecting_sys.service.IActivitiesService;
import com.dgut.courses_selecting_sys.service.IUserRoleService;
import com.dgut.courses_selecting_sys.utils.RedisUtil;
import com.dgut.courses_selecting_sys.utils.ShiroUtils;
import com.dgut.courses_selecting_sys.utils.core.BeanUtils;
import com.dgut.courses_selecting_sys.utils.core.StringUtils;
import com.dgut.courses_selecting_sys.vo.ActivityVo;
import com.dgut.courses_selecting_sys.vo.PageVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author yuec
 * @since 2021-01-26
 */
@Slf4j
@Service
public class ActivitiesServiceImpl extends ServiceImpl<ActivitiesMapper, Activities> implements IActivitiesService {

    @Autowired
    ActivitiesMapper activitiesMapper;
    @Autowired
    IUserRoleService userRoleService;
    @Autowired
    UserActivitiesMapper userActivitiesMapper;
    @Autowired
    RabbitTemplate rabbitTemplate;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    RedisUtil redisUtil;


    @Override
    public AjaxResult createActivity(ActivitiesDto activitiesDto) {
        Activities activities = new Activities();
        BeanUtils.copyBeanProp(activities, activitiesDto);
        String format = "yyyy-MM-dd'T'HH:mm";
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date startdate = null;
        Date enddate = null;
        Date selectedTime = null;
        try {
            startdate = sdf.parse(activitiesDto.getStartTime());
            enddate = sdf.parse(activitiesDto.getEndTime());
            selectedTime = sdf.parse(activitiesDto.getSelectedTime());
            if (startdate.getTime() > enddate.getTime()) {
                return AjaxResult.error("活动开始时间不能晚于结束时间");
            }
            if (startdate.getTime() < selectedTime.getTime()) {
                return AjaxResult.error("开选时间不得晚于活动开始时间");
            }
        } catch (ParseException e) {
            log.error("时间转换出异常");
            e.printStackTrace();
        }
        activities.setStartTime(startdate);
        activities.setEndTime(enddate);
        activities.setSelectedTime(selectedTime);
        activities.setCreateByName(ShiroUtils.getSysUser().getUserName());
        activities.setCreateBy(ShiroUtils.getUserId());
        activities.setStatus(ActivityStatus.PRE);
        Long id=null;
        if (activitiesMapper.insert(activities)==1){
            id=userActivitiesMapper.selectLastInsert();
        }
        if (id==null){
            return AjaxResult.error("数据库出错！");
        }
        //发送mq定时任务
        Date finalSelectedTime = selectedTime;
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        MessagePostProcessor messagePostProcessor = message -> {
            MessageProperties messageProperties = message.getMessageProperties();
//          设置编码
            messageProperties.setContentEncoding("utf-8");
//          设置延时时间
            long wait = finalSelectedTime.getTime() - System.currentTimeMillis();
            messageProperties.setExpiration(String.valueOf(wait));
            return message;
        };
        try{
            rabbitTemplate.convertAndSend(RabbitMqKey.MY_NORMAL_EXCHANGE, RabbitMqKey.ACTIVITY_ROUTING_KEY, JSON.toJSONString(id) , messagePostProcessor,correlationData);
        }catch (Exception e){
            return AjaxResult.error("创建活动出现异常");
        }
        return AjaxResult.success("活动创建成功");
    }

    @Override
    public AjaxResult editActivity(Activities activities) {
        if (ActivityStatus.PRE == activities.getStatus()) {
            if (activitiesMapper.updateById(activities) == 1) {
                return AjaxResult.success("活动修改成功过");
            }
            return AjaxResult.error("活动修改出现异常");
        }
        return AjaxResult.error("活动已生效，不能修改");
    }

    @Override
    public PageVo<Activities> getDataByActivityVo(ActivityVo activityVo) {
        QueryWrapper<Activities> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(activityVo.getActivityName())) {
            queryWrapper.like("activity_name", activityVo.getActivityName());
        }
        if (StringUtils.isNotEmpty(activityVo.getCreateByName())) {
            queryWrapper.like("create_by_name", activityVo.getCreateByName());
        }
        if (StringUtils.isNotNull(activityVo.getStartTime())) {
            queryWrapper.ge("start_time", activityVo.getStartTime());
        }
        if (StringUtils.isNotNull(activityVo.getEndTime())) {
            queryWrapper.le("end_time", activityVo.getEndTime());
        }
        if (StringUtils.isNotNull(activityVo.getStatus())) {
            queryWrapper.eq("status", activityVo.getStatus());
        }
        queryWrapper.orderByDesc("gmt_create");
        IPage<Activities> page = new Page<>(activityVo.getPageNumber(), activityVo.getPageSize());
        activitiesMapper.selectPage(page, queryWrapper);
        PageVo<Activities> pages = new PageVo<>();
        pages.setRows(page.getRecords());
        pages.setTotal(page.getTotal());
        return pages;
    }

    @Override
    public List<Activities> listActivities() {
        String key = RedisKey.ACTIVITIES_SELECTED + "*";
        Set keys = redisTemplate.keys(key);
        List<Activities> list = redisTemplate.opsForValue().multiGet(keys);
        if (StringUtils.isNull(list)||StringUtils.isEmpty(list)) {
            log.info("redis查询当前无可选活动！");
            return new ArrayList<>(0);
        }
        return list;
    }

    @Override
    public List checkUserActivitiesForChoose(User user) {
        List<UserActivities> list = userActivitiesMapper.selectList(new QueryWrapper<UserActivities>()
                .eq("user_id", user.getUserId()));
        if (list != null && list.size() != 0) {
            return list.stream().map(UserActivities::getActivityId).collect(Collectors.toList());
        }
        return null;
    }

    @Override
    @Transactional
    public AjaxResult chooseActivity(Long userId, Long activityId) {

        String keyNameForCount = RedisKey.ACTIVITY_COUNT + activityId;
        if (redisUtil.hasKey(keyNameForCount)) {
            Integer count = (Integer) redisUtil.get(keyNameForCount);
            if (count == null || count <= 0) {
                return AjaxResult.error("活动报选人数已达到上限！");
            } else {
                redisUtil.decr(keyNameForCount, 1L);
                Map map = new HashMap<String, Long>();
                map.put("userId", ShiroUtils.getSysUser().getUserId());
                map.put("activityId", activityId);
                rabbitTemplate.convertAndSend(RabbitMqKey.ACTIVITY_USER_CONSUMER, JSON.toJSONString(map));
                return AjaxResult.success("活动选报成功！请留意邮件通知");
            }
        } else {
            return AjaxResult.error("活动不可选或未开选！");
        }
    }

    @Override
    public AjaxResult unChooseActivity(Long userId, Long activityId) {
        Activities activities = activitiesMapper.selectById(activityId);
        if (activities.getStatus().equals(ActivityStatus.PRE)) {
            return AjaxResult.error("活动未开发选报");
        }
        if (activities.getStatus().equals(ActivityStatus.END)) {
            return AjaxResult.error("活动已结束不可修改");
        }
        Map map = new HashMap();
        map.put("user_id", userId);
        map.put("activity_id", activityId);
        if (userActivitiesMapper.deleteByMap(map) == 1) {
            log.info("课程退选::退选人编号->{}->退选人->{}->退选课程编号->{}", userId, ShiroUtils.getSysUser().getUserName(), activityId);
            return AjaxResult.success("退选成功");
        } else {
            return AjaxResult.error("退选失败!!!!");
        }
    }


}
